package com.zhanghe.study.web;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.SilentCssErrorHandler;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import icu.zhhll.util.json.GsonUtils;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 好大夫在线
 *
 * @author zh
 * @date 2023/10/11 15:23
 */
public class HttpUnitHaoDaiFu {

    static Logger log = LoggerFactory.getLogger("DOCTOR");

    // 创建连接池配置
    static ConnectionPool connectionPool = new ConnectionPool(5, 5, TimeUnit.MINUTES);
    // 创建OkHttpClient，并设置连接池
    static OkHttpClient client = new OkHttpClient.Builder()
            .connectionPool(connectionPool)
            .build();
    static MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");

    public static void main(String[] args) {
//        // 获取医院信息
//        writeHospital();
//        // 获取科室信息
//        writeAllHospitalDep();
        // 获取医生信息
        doctors();

    }

    public static void doctors() {
        try (BufferedReader reader = new BufferedReader(new FileReader("fen/keshi0.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                Department department = GsonUtils.instance().fromJson(line, Department.class);
                System.out.println(department.getHospitalId()+"========="+ department.getId());
                getDoctorPage(department.getHospitalId(), department.getId(), 1);

            }
        } catch ( IOException e) {
            e.printStackTrace();
        }
    }

    public static void getDoctorPage(String hospitalId, String depId, int pageNo) {
        String params = "hospitalId=" + hospitalId + "&hospitalFacultyId=" + depId + "&nowPage=" + pageNo;
        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url("https://www.haodf.com/nhospital/pc/keshi/ajaxHosTuijianDocList")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        try (okhttp3.Response response = client.newCall(request).execute();){

            if (response.isSuccessful()) {
                String string = response.body().string();
                if (StringUtils.isNotBlank(string)) {
                    JSONObject object = JSON.parseObject(string);
                    if (object.containsKey("errorCode") && object.getIntValue("errorCode") == 0) {
                        if (object.containsKey("data")) {
                            JSONArray jsonArray = object.getJSONArray("data");
                            if (jsonArray != null && jsonArray.size() > 0) {
                                for (int i = 0; i < jsonArray.size(); i++) {
                                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                                    if (jsonObject.containsKey("doctorId")) {
                                        long doctorId = jsonObject.getLongValue("doctorId");
                                        getDoctorInfo(hospitalId, depId, doctorId);
                                    }
                                }
                                // 进行下一页
                                getDoctorPage(hospitalId, depId, pageNo + 1);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void getDoctorInfo(String hospitalId, String depId, long doctorId) {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String params = "doctorId=" + doctorId;
        RequestBody body = RequestBody.create(mediaType, params);
        Request request = new Request.Builder()
                .url("https://www.haodf.com/ndoctor/ajaxGetDoctorSchedule4NotSpace")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        try (okhttp3.Response response = client.newCall(request).execute();){

            if (response.isSuccessful()) {
                String string = response.body().string();
                if (StringUtils.isNotBlank(string)) {
                    JSONObject object = JSON.parseObject(string);
                    if (object.containsKey("errorCode") && object.getIntValue("errorCode") == 0) {
                        if (object.containsKey("data")) {
                            JSONObject jsonObject = object.getJSONObject("data");
                            if (jsonObject != null) {
                                if (jsonObject.containsKey("hospitalSchedule")) {
                                    JSONArray hospitalSchedules = jsonObject.getJSONArray("hospitalSchedule");
                                    if (hospitalSchedules != null && hospitalSchedules.size() > 0) {
                                        JSONObject hospitalSchedule = hospitalSchedules.getJSONObject(0);
                                        DoctorInfo doctorInfo = new DoctorInfo();
                                        doctorInfo.setHospitalId(hospitalId);
                                        doctorInfo.setDepartmentId(depId);
                                        doctorInfo.setId(doctorId);
                                        if (hospitalSchedule.containsKey("doctorInfo")) {
                                            JSONObject doctorObject = hospitalSchedule.getJSONObject("doctorInfo");
                                            doctorInfo.setName(doctorObject.getString("name"));
                                            doctorInfo.setSex(doctorObject.getIntValue("sex"));
                                            doctorInfo.setGrade(doctorObject.getString("grade"));
                                            doctorInfo.setEducateGrade(doctorObject.getString("educateGrade"));
                                            doctorInfo.setBriefIntro(doctorObject.getString("briefIntro"));
                                            doctorInfo.setSpecialize(doctorObject.getString("specialize"));
                                            doctorInfo.setFacultyName(doctorObject.getString("facultyName"));
                                        }

                                        if (hospitalSchedule.containsKey("docPriFacultyRefInfo")) {
                                            JSONObject doctorObject = hospitalSchedule.getJSONObject("docPriFacultyRefInfo");
                                            doctorInfo.setFacultyName(doctorObject.getString("facultyName"));
                                        }

                                        if (hospitalSchedule.containsKey("scheduleList")) {
                                            JSONArray scheduleArray = hospitalSchedule.getJSONArray("scheduleList");
                                            List<Schedule> schedules = new ArrayList<>();
                                            doctorInfo.setScheduleList(schedules);
                                            if (scheduleArray != null && scheduleArray.size() > 0) {
                                                for (int i = 0; i < scheduleArray.size(); i++) {
                                                    JSONObject scheduleObject = scheduleArray.getJSONObject(i);

                                                    Schedule schedule = new Schedule();

                                                    schedule.setScheduleDate(scheduleObject.getString("scheduleDate"));
                                                    schedule.setFeeStrType(scheduleObject.getString("feeStrType"));
                                                    schedule.setWeekday(scheduleObject.getString("weekday"));
                                                    schedule.setTime(scheduleObject.getString("time"));
                                                    schedules.add(schedule);
                                                }
                                            }


                                        }

                                        log.info(GsonUtils.instance().toJson(doctorInfo));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 医院
     */
    public static void writeHospital() {

        try (FileWriter writer = new FileWriter("hos.txt", false);
             WebClient webClient = new WebClient()) {
            //新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

            webClient.getOptions().setThrowExceptionOnScriptError(true);//当JS执行出错的时候是否抛出异常, 这里选择不需要
            webClient.getOptions().setThrowExceptionOnFailingStatusCode(true);//当HTTP的状态非200时是否抛出异常, 这里选择不需要
            webClient.getOptions().setActiveXNative(true);
            webClient.getOptions().setCssEnabled(false);//是否启用CSS, 因为不需要展现页面, 所以不需要启用
            webClient.getOptions().setJavaScriptEnabled(true); //很重要，启用JS
//忽略css错误
            webClient.setCssErrorHandler(new SilentCssErrorHandler());
            webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要，设置支持AJAX
//超时时间
            webClient.getOptions().setTimeout(3000);
            //允许重定向
            webClient.getOptions().setRedirectEnabled(true);
            //允许cookie
            webClient.getCookieManager().setCookiesEnabled(true);
            HtmlPage page = webClient.getPage("https://www.haodf.com/hospital/list-44.html");//广东

            webClient.waitForBackgroundJavaScript(3000);
            String pageXml = page.asXml();//直接将加载完成的页面转换成xml格式的字符串

            Document document = Jsoup.parse(pageXml);//获取html文档
            Element content = document.getElementById("el_result_content");
            if (content != null) {

                Elements ct = content.getElementsByClass("ct");
                if (ct != null && ct.size() > 0) {
                    // 医院列表
                    Elements hospitalList = ct.get(0).getElementsByTag("a");
                    for (Element hospital : hospitalList) {
                        Hospital hos = new Hospital();
                        String text = hospital.text();
                        String href = hospital.attr("href");
                        System.out.println(hospital);

                        hos.setName(text);
                        hos.setUrl(href);
                        hos.setId(href.substring(href.lastIndexOf("/") + 1, href.lastIndexOf(".")));
                        writer.write(GsonUtils.instance().toJson(hos) + "\n");
                        writer.flush();
                    }

                }
            }
//            System.out.println(pageXml);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void writeAllHospitalDep() {
        try (BufferedReader reader = new BufferedReader(new FileReader("hos.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {

                Hospital hospital = GsonUtils.instance().fromJson(line, Hospital.class);
                writeHospitalDep(hospital.getId());
                Thread.sleep(10000);
            }
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 科室
     *
     * @throws IOException
     */
    public static void writeHospitalDep(String hospitalId) {
        List<Hospital> hospitals = new ArrayList<>();

        try (FileWriter writer = new FileWriter("keshi.txt", true);
             WebClient webClient = new WebClient()) {
            //新建一个模拟谷歌Chrome浏览器的浏览器客户端对象

            webClient.getOptions().setThrowExceptionOnScriptError(true);//当JS执行出错的时候是否抛出异常, 这里选择不需要
            webClient.getOptions().setThrowExceptionOnFailingStatusCode(true);//当HTTP的状态非200时是否抛出异常, 这里选择不需要
            webClient.getOptions().setActiveXNative(true);
            webClient.getOptions().setCssEnabled(false);//是否启用CSS, 因为不需要展现页面, 所以不需要启用
            webClient.getOptions().setJavaScriptEnabled(true); //很重要，启用JS
//忽略css错误
            webClient.setCssErrorHandler(new SilentCssErrorHandler());
            webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要，设置支持AJAX
//超时时间
            webClient.getOptions().setTimeout(3000);
            //允许重定向
            webClient.getOptions().setRedirectEnabled(true);
            //允许cookie
            webClient.getCookieManager().setCookiesEnabled(true);
            // 科室
            HtmlPage page = webClient.getPage("https://www.haodf.com/hospital/" + hospitalId + "/keshi/list.html");

            webClient.waitForBackgroundJavaScript(3000);
            String pageXml = page.asXml();//直接将加载完成的页面转换成xml格式的字符串

            Document document = Jsoup.parse(pageXml);//获取html文档
            Elements contents = document.getElementsByClass("hos-keshi");
            if (contents != null && contents.size() > 0) {
                Element content = contents.get(0);
                Elements keshiNames = content.getElementsByClass("keshi-name-showall");
                if (keshiNames != null && keshiNames.size() > 0) {
                    // 主科室列表
                    for (int i = 0; i < keshiNames.size(); i++) {
                        // 主科室名称
                        Element element = keshiNames.get(i);
                        String mainName = element.text().trim();
                        // 科室
                        Element anchor = content.getElementById("anchor" + i);
                        if (anchor != null) {
                            // 科室列表
                            Elements keshiList = anchor.getElementsByTag("li");
                            if (keshiList != null && keshiList.size() > 0) {
                                for (Element ele : keshiList) {
                                    Department department = new Department();
                                    department.setHospitalId(hospitalId);
                                    department.setMainName(mainName);
                                    Elements a = ele.getElementsByTag("a");
                                    if (a != null && a.size() > 0) {
                                        Element element1 = a.get(0);
                                        String href = element1.attr("href");
                                        department.setUrl(href);
                                        department.setId(href.substring(href.lastIndexOf("/") + 1, href.lastIndexOf(".")));
                                        Elements name = element1.getElementsByClass("name-txt");
                                        if (name != null && name.size() > 0) {
                                            department.setName(name.get(0).text());
                                        }

                                        Elements count = element1.getElementsByClass("count");
                                        if (count != null && count.size() > 0) {
                                            department.setCount(count.get(0).text());
                                        }

                                    }
                                    writer.write(GsonUtils.instance().toJson(department) + "\n");
                                    writer.flush();

                                }
                            }
                        }

                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    static class Hospital {
        private String name;
        private String url;
        private String id;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }
    }

    // https://www.haodf.com/hospital/443/keshi/list.html
    static class Department {
        // 主科室
        private String mainName;
        private String name;
        private String url;
        private String id;
        // 有多少个医生
        private String count;
        private String hospitalId;

        public String getMainName() {
            return mainName;
        }

        public void setMainName(String mainName) {
            this.mainName = mainName;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getCount() {
            return count;
        }

        public void setCount(String count) {
            this.count = count;
        }

        public String getHospitalId() {
            return hospitalId;
        }

        public void setHospitalId(String hospitalId) {
            this.hospitalId = hospitalId;
        }
    }

    static class DoctorInfo {
        private String hospitalId;
        private String departmentId;

        // =====doctorInfo

        private long id;
        private String name;
        // 1表示男
        private int sex;
        // 称号
        private String grade;
        private String educateGrade;
        // 简介
        private String briefIntro;
        // 专业领域
        private String specialize;

        // ===== docPriFacultyRefInfo
        // 专业方向
        private String facultyName;

        // ===== scheduleList 排班
        private List<Schedule> scheduleList;

        public String getHospitalId() {
            return hospitalId;
        }

        public void setHospitalId(String hospitalId) {
            this.hospitalId = hospitalId;
        }

        public String getDepartmentId() {
            return departmentId;
        }

        public void setDepartmentId(String departmentId) {
            this.departmentId = departmentId;
        }

        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getSex() {
            return sex;
        }

        public void setSex(int sex) {
            this.sex = sex;
        }

        public String getGrade() {
            return grade;
        }

        public void setGrade(String grade) {
            this.grade = grade;
        }

        public String getEducateGrade() {
            return educateGrade;
        }

        public void setEducateGrade(String educateGrade) {
            this.educateGrade = educateGrade;
        }

        public String getBriefIntro() {
            return briefIntro;
        }

        public void setBriefIntro(String briefIntro) {
            this.briefIntro = briefIntro;
        }

        public String getSpecialize() {
            return specialize;
        }

        public void setSpecialize(String specialize) {
            this.specialize = specialize;
        }

        public String getFacultyName() {
            return facultyName;
        }

        public void setFacultyName(String facultyName) {
            this.facultyName = facultyName;
        }

        public List<Schedule> getScheduleList() {
            return scheduleList;
        }

        public void setScheduleList(List<Schedule> scheduleList) {
            this.scheduleList = scheduleList;
        }
    }

    static class Schedule {
        // 日期
        private String scheduleDate;
        // 门诊信息
        private String feeStrType;
        // 周几
        private String weekday;
        // 上午还是下午
        private String time;

        public String getScheduleDate() {
            return scheduleDate;
        }

        public void setScheduleDate(String scheduleDate) {
            this.scheduleDate = scheduleDate;
        }

        public String getFeeStrType() {
            return feeStrType;
        }

        public void setFeeStrType(String feeStrType) {
            this.feeStrType = feeStrType;
        }

        public String getWeekday() {
            return weekday;
        }

        public void setWeekday(String weekday) {
            this.weekday = weekday;
        }

        public String getTime() {
            return time;
        }

        public void setTime(String time) {
            this.time = time;
        }
    }


}
